using System;
using System.Text;
using System.Xml;

namespace Slaks.DocumentSerialization.Dictionary
{
	/*
	 *  <local_dictionary_info>
	 *    <total>2</total>
	 *    <entry id="2" />
	 *    <entry id="3" />
	 *  </local_dictionary_info>
	 */

	public class DictionaryInfo
	{
		/// <summary>
		/// Write the dictionary
		/// </summary>
		/// <param name="path">filename where to save dictionary</param>
		/// <param name="dictionary">Dictionary with keys as id (typeof(long))</param>
		/// <param name="size">size of the idEnumerator</param>
		public static void XmlWrite(string path, DictionaryMap dictionary, int size)
		{
			XmlTextWriter writer = null;

			try
			{
				writer = new XmlTextWriter(path, Encoding.UTF8);
				writer.Formatting = Formatting.Indented;
				writer.WriteStartDocument();

				writer.WriteStartElement(Grammar.DictionaryInfo.DictionaryInfoElement);

				writer.WriteElementString(Grammar.DictionaryInfo.TotalElement, size.ToString());

				foreach (long id in dictionary.Keys)
				{
					writer.WriteStartElement(Grammar.DictionaryInfo.EntryElement);

					writer.WriteStartAttribute(Grammar.DictionaryInfo.IdAttr, "");
					writer.WriteString(id.ToString());
					writer.WriteEndAttribute();

					writer.WriteEndElement();
				}

				writer.WriteEndElement();
				writer.WriteEndDocument();
			}
			catch (Exception ex)
			{
				throw ex;
			}
			finally
			{
				writer.Close();
			}
		}

		public static DictionaryMap ReadXml(string filename)
		{
			DictionaryMap map = new DictionaryMap();
			object DUMMY = new object();
			XmlReader reader = null;
			try
			{
				reader = new XmlTextReader(filename);
				long index = 0;
				long total = SkipTotal(reader);
				if (total < 0) return null;

				long id;
				while (index < total)
				{
					id = ReadTermIdInfo(reader);
					if (id < 0) break;
					map.Add(id, DUMMY);
					++index;
				}
			}
			catch (Exception ex)
			{
				throw ex;
			}
			finally
			{
				if (reader != null) reader.Close();
			}

			return map;
		}

		private static long SkipTotal(XmlReader reader)
		{
			while (reader.Read())
			{
				if (reader.NodeType != XmlNodeType.Element) continue;
				if (string.Equals(Grammar.DictionaryInfo.TotalElement, reader.Name))
				{
					return long.Parse(reader.ReadElementString(reader.Name));
				}
			}
			return -1;
		}

		private static long ReadTermIdInfo(XmlReader reader)
		{
			long id = -1000;
			while (reader.Read())
			{
				if (reader.NodeType != XmlNodeType.Element) continue;
				if (string.Equals(Grammar.DictionaryInfo.EntryElement, reader.Name))
				{
					reader.MoveToAttribute(Grammar.TermIdInfo.IdAttr);
					id = long.Parse(reader.Value);
					break;
				}
			}
			return id;
		}
	}
}